﻿using Mozhi.Abp.Core.Extensions;
using Mozhi.Abp.Domain.AuthorCenter;
using Mozhi.Abp.Domain.BasicData;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;

namespace mozhi.smarterp.Business.Purchases
{
    /// <summary>
    /// 采购入库
    /// </summary>
    public class PurchaseReceipt : DocumentAggregateRoot<PurchaseReceiptItem>
    {
        /// <summary>
        /// 是否退货
        /// </summary>
        public bool IsCreditNote { get; private set; }

        /// <summary>
        /// 仓管员
        /// </summary>
        public Guid WarehouseClerkId { get; private set; }

        public Employee WarehouseClerk {  get; private set; }

        #region 订单携带信息
        /// <summary>
        /// 供应商
        /// </summary>
        public Guid? SupplierId { get; private set; }

        /// <summary>
        /// 采购部门
        /// </summary>
        public Guid? PurchaseDepartmentId { get; private set; }


        /// <summary>
        /// 采购员
        /// </summary>
        public Guid? PurchaserId { get; private set; }


        public Guid? PaymentTemrId { get; private set; }

        #endregion


        protected PurchaseReceipt() { }

        public PurchaseReceipt(Guid id , string number , DateTime date , bool includeTax , Currency currency , decimal exchangeRate , bool isCreditNote,Department department,
            Employee warehouseClerk, Guid supplierId,  Guid purchaseDepartmentId, Guid purchaserId , Guid? paymentTemrId  , string comment):
            base(id , number , date , includeTax , currency , exchangeRate , department, comment)
        {
            WarehouseClerk = warehouseClerk;

            Id = id;
            IsCreditNote = isCreditNote;
            
            WarehouseClerkId = warehouseClerk==null ? default: warehouseClerk.Id;
        
            SupplierId = supplierId;
            PurchaseDepartmentId = purchaseDepartmentId;
            PurchaserId = purchaserId;
            PaymentTemrId = paymentTemrId;

            Items = new List<PurchaseReceiptItem>();

            Validate();
        }

        public void Change(DateTime date, bool includeTax, Currency currency, decimal exchangeRate, bool isCreditNote, Department department,
            Employee warehouseClerk)
        {
            WarehouseClerk = warehouseClerk;
            Currency = currency;
            Department = department;

            Date = date;
            IncludeTax = includeTax;
            ExchangeRate = exchangeRate;
            
            IsCreditNote = isCreditNote;

            WarehouseClerkId = warehouseClerk == null ? default : warehouseClerk.Id;
        }

        #region
        protected override void Validate()
        {
            base.Validate();

            if (WarehouseClerk != null)
                WarehouseClerk.Validate();

            Check.NotDefaultOrNull(SupplierId, nameof(SupplierId));
        }

   
        protected override void AddOrUpdateItem(PurchaseReceiptItem item)
        {
            var match = Items.FirstOrDefault(x => x.Id == item.Id);

            if (match == null)
            {
                match = item;

                match.CalculateAmount(IncludeTax, ExchangeRate);
                Items.Add(match);
            }

            else
            {
                match.Change(item.Product, item.Warehouse, item.LocationId, item.PurchaseUnitId, item.ReceivableQuantity, item.AuxiliaryQuantity, item.BasicQuantity, item.TaxRate, item.BatchNumber, item.SerialNumber, item.ProductionDate,
                    item.ShelfLifeDays, item.IsGift, item.Remark);

                item.CalculateAmount(IncludeTax, ExchangeRate);
            }
        }

        #endregion
    }

    public class PurchaseReceiptItem : DocumentEntity
    {
        public Guid WarehouseId { get; private set; }

        public Warehouse Warehouse { get; private set; }

        public Guid? LocationId { get; private set; }

        public Guid PurchaseUnitId { get; private set; }

        /// <summary>
        /// 应收数量
        /// </summary>
        public decimal ReceivableQuantity { get; private set; }


        public string BatchNumber { get; private set; }

        public string SerialNumber { get; private set; }

        /// <summary>
        /// 生产日期
        /// </summary>
        public DateTime? ProductionDate { get; private set; }

        /// <summary>
        /// 保质期（天）
        /// </summary>
        public decimal? ShelfLifeDays {  get; private set; }

        /// <summary>
        /// 过期日期
        /// </summary>
        public DateTime? ExpirationDate {  get; private set; }

        /// <summary>
        /// 成本单价(原币)
        /// </summary>
        public decimal? CostPriceFr { get; private set; }

        public decimal? CostPrice { get; private set; }

        public decimal? TotalCostPriceFr { get; private set; }

        public decimal? TotalCostPrice {  get; private set; }

        public bool IsGift { get; private set; }

        private PurchaseReceiptItem() { }

        public PurchaseReceiptItem(Guid id, Product product, Warehouse warehouse, Guid? locationId, ProductAuxiliaryUnit auxiliaryUnit, Unit purchaseUnit, decimal receivableQuantity, decimal receivedQuantity, decimal basicQuantity, decimal price, TaxRate taxRate,
            string batchNumber, string serialNumber, DateTime? productionDate, decimal? shelfLifeDays, bool isGift, string remark)
            : base(id, product, purchaseUnit, auxiliaryUnit, receivedQuantity, price, taxRate, remark)
        {
            Warehouse = warehouse;

            Id = id;

            WarehouseId = Warehouse == null ? default : Warehouse.Id;
            LocationId = locationId;
            PurchaseUnitId = purchaseUnit.Id;
            ReceivableQuantity = receivableQuantity;
            AuxiliaryQuantity = receivedQuantity;
            BasicQuantity = basicQuantity;

            BatchNumber = batchNumber;
            SerialNumber = serialNumber;
            ProductionDate = productionDate;
            ShelfLifeDays = shelfLifeDays;

            CalculateExpirationDate();

            IsGift = isGift;
            Remark = remark;

            Validate();
        }

        public void Change(Product product, Warehouse warehouse, Guid? locationId, Guid purchaseUnitId, decimal receivableQuantity, decimal receivedQuantity, decimal basicQuantity, TaxRate taxRate,
            string batchNumber, string serialNumber, DateTime? productionDate, decimal? shelfLifeDays,  bool isGift, string remark)
        {
            Warehouse = warehouse;
            Product = product;
            TaxRate = taxRate;

            ProductId = Product== null ? default : Product.Id;
            WarehouseId = Warehouse == null ? default : Warehouse.Id;
            LocationId = locationId;
            PurchaseUnitId = purchaseUnitId;
            ReceivableQuantity = receivableQuantity;
            AuxiliaryQuantity = receivedQuantity;
            TaxRateId = TaxRate == null ? default : TaxRate.Id;
            TaxRateValue = TaxRate == null ? default : TaxRate.Rate;
            BasicQuantity = basicQuantity;

            BatchNumber = batchNumber;
            SerialNumber = serialNumber;
            ProductionDate = productionDate;
            ShelfLifeDays = shelfLifeDays;
            CalculateExpirationDate();
            IsGift = isGift;
            Remark = remark;

            Validate();
        }

        public void CalculateExpirationDate()
        {
            if (!ShelfLifeDays.HasValue || !ProductionDate.HasValue)
                ExpirationDate = null;
            else
                ExpirationDate = ProductionDate.Value.AddDays((double)ShelfLifeDays.Value);
        }

        #region
        protected override void Validate()
        {
            base.Validate();

            if (Warehouse == null)
                throw new UserFriendlyException("仓库不存在", "100000");

            Warehouse.Validate();
            Warehouse.ValidateLoaction(LocationId);

            if (AuxiliaryQuantity <= 0)
                throw new UserFriendlyException("实收数量必须大于0", "100000");

            Check.NotDefaultOrNull<decimal>(ReceivableQuantity , nameof(ReceivableQuantity));
        }
        #endregion
    }
}
